home *** CD-ROM | disk | FTP | other *** search
-
- ****************************************************************
- *
- * Copyright 1988 by CREATIVE FOCUS. This code is freely
- * distributable as long as this notice is retained and no
- * other conditions are imposed upon its redistribution.
- *
- *
- * APACK.ASM --
- *
- * A fully compatible replacement for Electronic Arts' PACKER.C
- * routine. Converts data according to the IFF ILBM cmpByteRun1
- * compression protocol:
- *
- * control bytes:
- *
- * n = 0.. 127: followed by n+1 bytes of data;
- * n = -1..-127: followed by byte to be repeated -n+1 times;
- * n = -128: don't do no nada.
- *
- * calling format:
- *
- * long packrow(from, too, amt)
- * char **from, /* pointer to source data pointer */
- * **too; /* pointer to destination data pointer */
- * long amt; /* number of bytes to compress */
- *
- * return(number of bytes written to destination);
- *
- * effects:
- *
- * *from = *from + amt, and *too = *too + return;
- * return is "smart," that is, not greater than
- * MaxPackedSize = amt + ((amt+127) >> 7).
- *
- * By commenting out CHECK (below) you disable checking for runs
- * exceeding 128 bytes. That CHECK is not needed if you are sure
- * the amt to be compressed is always 128 or less.
- *
- * !!! DISCLAIMER !!! You use this code entirely at your own
- * risk. I don't warrantee its fitness for any purpose. I
- * can't even guarantee the accuracy of anything I've said
- * about it, though I've tried my damndest to get it right.
- * I may, in fact, be completely out of my tiny little mind :-).
- *
- * That being said, I can be reached for questions, comments,
- * or concerns at:
- *
- * Dr. Gerald Hull
- * CREATIVE FOCUS
- * 12 White Street
- * Binghamton, N.Y. 13901
- * (607) 648-4082
- *
- * bix: ghull
- * PLink: DRJERRY
- *
- ***************************************************************
-
- * edited by mjp to compile with SAS/C 5.10
-
- xdef _packrow
-
- section code
-
- *a0 equr a0 -> beginning of replicate run (if any)
- *a1 equr a1 -> end+1 of input line
- *a2 equr a2 -> beginning of literal run (if any)
- *a3 equr a3 -> end+1 of lit and/or rep run (if any)
- *a4 equr a4 -> end+1 of output line current pos
- *a5 equr a6 frame pointer
- *a7 equr a7 stack pointer
-
- *d0 equr d0 return value
- *d1 equr d1 check for maximum run = MAX
- *d2 equr d2 amount
- *d3 equr d3 character
-
- *d2/d3/a2/a3/a4 reg d2/d3/a2/a3/a4
-
- FRM equ 8 input line address
- TOO equ 12 output line address
- AMT equ 16 length of input line
-
- MAX equ 128 maximum encodable output run
- CHECK equ 1 turns on maximum row checking
-
-
- _packrow
-
-
- *************** CASE 0: GRAB PARAMS & INITIALIZE
- CAS0
- link a5,#0
- movem.l d2/d3/a2/a3/a4,-(a7)
- movea.l FRM(a5),a2
- movea.l (a2),a2 a2 = *from
- movea.l a2,a3 a3 = a2
- movea.l a3,a1
- adda.l AMT(a5),a1 a1 = a2 + amt
- movea.l TOO(a5),a4
- movea.l (a4),a4 a4 = *too
-
-
- *************** CASE 1: LITERAL RUN
- CAS1
- movea.l a3,a0 adjust a0 (no replicates yet!)
- move.b (a3)+,d3 grab character
- cmpa.l a3,a1 if input is finished
- beq.s CAS5 branch to case 5
-
- ifd CHECK
- move.l a3,d1
- sub.l a2,d1
- cmpi #MAX,d1 if run has reached MAX
- beq.s CAS6 branch to case 6
- endc
-
- cmp.b (a3),d3 if next character != d3
- bne.s CAS1 stay in case 1
-
- * else fall into case 2
-
-
- *************** CASE 2: AT LEAST 2 BYTE REPEAT
- CAS2
- move.b (a3)+,d3 grab character
- cmpa.l a3,a1 if input is finished
- beq.s CAS7 branch to case 7
-
- ifd CHECK
- move.l a3,d1
- sub.l a2,d1
- cmpi #MAX,d1 if run has reached MAX
- beq.s CAS6 branch to case 6
- endc
-
- cmp.b (a3),d3 if next character != d3
- bne.s CAS1 branch to case 1
-
- * else fall into case 3
-
-
- *************** CASE 3: REPLICATE RUN
- CAS3
- move.b (a3)+,d3 grab character
- cmpa.l a3,a1 if input is finished
- beq.s CAS7 branch to case 7
-
- ifd CHECK
- move.l a3,d1
- sub.l a0,d1
- cmpi #MAX,d1 if run has reached MAX
- beq.s CAS4 branch to case 4
- endc
-
- cmp.b (a3),d3 if next character = d3
- beq.s CAS3 stay in case 3
-
- * else fall into case 4
-
-
- *************** CASE 4: LIT AND/OR REP DUMP & CONTINUE
- CAS4
- move.l a0,d2
- sub.l a2,d2 d2 = a0 - a2
- * if no literal run
- beq.s C41 branch to replicate run
-
- subq #1,d2 d2 = d2 - 1
- move.b d2,(a4)+ output literal control byte
-
- C40 move.b (a2)+,(a4)+ output literal run
- dbra d2,C40
-
- C41 move.l a0,d2
- sub.l a3,d2 d2 = a0 - a3 (negative result!)
- addq #1,d2 d2 = d2 + 1
- move.b d2,(a4)+ output replicate control byte
- move.b d3,(a4)+ output repeated character
- movea.l a3,a2 reset a2
- bra.s CAS1 branch to case 1 (not done)
-
-
- *************** CASE 5: LITERAL DUMP & QUIT
- CAS5
- move.l a3,d2
- sub.l a2,d2 d2 = a3 - a2 (positive result > 0)
- subq #1,d2 d2 = d2 - 1
- move.b d2,(a4)+ output literal control byte
-
- C50 move.b (a2)+,(a4)+ output literal run
- dbra d2,C50
-
- bra.s CAS8 branch to case 8 (done)
-
-
- ifd CHECK
-
- *************** CASE 6: LITERAL DUMP & CONTINUE
- CAS6
- move.l a3,d2
- sub.l a2,d2 d2 = a3 - a2 (positive result > 0)
- subq #1,d2 d2 = d2 - 1
- move.b d2,(a4)+ output literal control byte
-
- C60 move.b (a2)+,(a4)+ output literal run
- dbra d2,C60
-
- bra CAS1 branch to case 1 (not done)
-
- endc
-
-
- *************** CASE 7: LIT AND/OR REP DUMP & FINISH
- CAS7
- move.l a0,d2
- sub.l a2,d2 d2 = a0 - a2 (positive result > 0)
- * if no literal run
- beq.s C71 branch to replicate run
-
- subq #1,d2 d2 = d2 - 1
- move.b d2,(a4)+ output literal control byte
-
- C70 move.b (a2)+,(a4)+ output literal run
- dbra d2,C70
-
- C71 move.l a0,d2
- sub.l a3,d2 d2 = a0 - a3 (negative result)
- addq #1,d2 d2 = d2 + 1
- move.b d2,(a4)+ output replicate control byte
- move.b d3,(a4)+ output repeated character
-
- * fall into case 8
-
-
- *************** CASE 8: ADJUST PARAMS & RETURN VALUE
- CAS8
- movea.l FRM(a5),a0 a0 = **from
- move.l a3,(a0) *from = *from + amt
- movea.l TOO(a5),a0 a0 = **too
-
- move.l a4,d0
- sub.l (a0),d0 return = a4 - *too
-
- move.l a4,(a0) *too = *too + return
- movem.l (a7)+,d2/d3/a2/a3/a4
- UNLK a5
- rts
-
- end
-
-
-